package labox.innovation.gameserver.network;

import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.concurrent.RejectedExecutionException;

import labox.innovation.config.Config;
import labox.innovation.gameserver.LoginServerThread;
import labox.innovation.gameserver.ThreadPoolManager;
import labox.innovation.gameserver.network.L2GameClient.GameClientState;
import labox.innovation.gameserver.network.clientpackets.Action;
import labox.innovation.gameserver.network.clientpackets.AnswerTradeRequest;
import labox.innovation.gameserver.network.clientpackets.AttackCancle;
import labox.innovation.gameserver.network.clientpackets.AttackRequest;
import labox.innovation.gameserver.network.clientpackets.AuthLogin;
import labox.innovation.gameserver.network.clientpackets.AutoPKInfo;
import labox.innovation.gameserver.network.clientpackets.AutoPkSet;
import labox.innovation.gameserver.network.clientpackets.AutoPkSetState;
import labox.innovation.gameserver.network.clientpackets.BuyItemConsignment;
import labox.innovation.gameserver.network.clientpackets.ChangeTradeItem;
import labox.innovation.gameserver.network.clientpackets.CharacterCreate;
import labox.innovation.gameserver.network.clientpackets.CharacterDelete;
import labox.innovation.gameserver.network.clientpackets.CharacterRestore;
import labox.innovation.gameserver.network.clientpackets.ChatSwitchPacket;
import labox.innovation.gameserver.network.clientpackets.EnterWorld;
import labox.innovation.gameserver.network.clientpackets.FetchItemConsignment;
import labox.innovation.gameserver.network.clientpackets.GameGuardReply;
import labox.innovation.gameserver.network.clientpackets.L2GameClientPacket;
import labox.innovation.gameserver.network.clientpackets.Location;
import labox.innovation.gameserver.network.clientpackets.Logout;
import labox.innovation.gameserver.network.clientpackets.MerchantRequest;
import labox.innovation.gameserver.network.clientpackets.NewCharacter;
import labox.innovation.gameserver.network.clientpackets.ProtocolVersion;
import labox.innovation.gameserver.network.clientpackets.RadarInfo;
import labox.innovation.gameserver.network.clientpackets.RankListRequest;
import labox.innovation.gameserver.network.clientpackets.RankRequest;
import labox.innovation.gameserver.network.clientpackets.RequestAnswerJoinParty;
import labox.innovation.gameserver.network.clientpackets.RequestAquireskill;
import labox.innovation.gameserver.network.clientpackets.RequestAssignPoint;
import labox.innovation.gameserver.network.clientpackets.RequestAutoLevelUp;
import labox.innovation.gameserver.network.clientpackets.RequestBypassToServer;
import labox.innovation.gameserver.network.clientpackets.RequestCanShelveItems;
import labox.innovation.gameserver.network.clientpackets.RequestChangeDistribution;
import labox.innovation.gameserver.network.clientpackets.RequestChangePkModel;
import labox.innovation.gameserver.network.clientpackets.RequestCompositeItem;
import labox.innovation.gameserver.network.clientpackets.RequestConItemByCategory;
import labox.innovation.gameserver.network.clientpackets.RequestConItemHigh;
import labox.innovation.gameserver.network.clientpackets.RequestConsignmentUI;
import labox.innovation.gameserver.network.clientpackets.RequestDeposit;
import labox.innovation.gameserver.network.clientpackets.RequestDepositGUI;
import labox.innovation.gameserver.network.clientpackets.RequestDisbandParty;
import labox.innovation.gameserver.network.clientpackets.RequestDropItem;
import labox.innovation.gameserver.network.clientpackets.RequestEffectBuff;
import labox.innovation.gameserver.network.clientpackets.RequestExRqItemLink;
import labox.innovation.gameserver.network.clientpackets.RequestForgeItem;
import labox.innovation.gameserver.network.clientpackets.RequestForgeItemChange;
import labox.innovation.gameserver.network.clientpackets.RequestFriendDel;
import labox.innovation.gameserver.network.clientpackets.RequestFriendInvite;
import labox.innovation.gameserver.network.clientpackets.RequestFriendList;
import labox.innovation.gameserver.network.clientpackets.RequestFriendsNews;
import labox.innovation.gameserver.network.clientpackets.RequestIdentifyItem;
import labox.innovation.gameserver.network.clientpackets.RequestItemList;
import labox.innovation.gameserver.network.clientpackets.RequestItemShelf;
import labox.innovation.gameserver.network.clientpackets.RequestItemShelve;
import labox.innovation.gameserver.network.clientpackets.RequestJoinParty;
import labox.innovation.gameserver.network.clientpackets.RequestLevelUp;
import labox.innovation.gameserver.network.clientpackets.RequestMagicSkillUse;
import labox.innovation.gameserver.network.clientpackets.RequestNearbyPlayer;
import labox.innovation.gameserver.network.clientpackets.RequestOutPartyMember;
import labox.innovation.gameserver.network.clientpackets.RequestPageTurning;
import labox.innovation.gameserver.network.clientpackets.RequestPartyInfo;
import labox.innovation.gameserver.network.clientpackets.RequestPcSkillList;
import labox.innovation.gameserver.network.clientpackets.RequestQuestAbort;
import labox.innovation.gameserver.network.clientpackets.RequestQuestList;
import labox.innovation.gameserver.network.clientpackets.RequestQuestSelect;
import labox.innovation.gameserver.network.clientpackets.RequestRestartPoint;
import labox.innovation.gameserver.network.clientpackets.RequestSearchFriends;
import labox.innovation.gameserver.network.clientpackets.RequestSetInfo;
import labox.innovation.gameserver.network.clientpackets.RequestSetPartyInfo;
import labox.innovation.gameserver.network.clientpackets.RequestShelveOfShelfItem;
import labox.innovation.gameserver.network.clientpackets.RequestShopItem;
import labox.innovation.gameserver.network.clientpackets.RequestShopItemsList;
import labox.innovation.gameserver.network.clientpackets.RequestShortCutDel;
import labox.innovation.gameserver.network.clientpackets.RequestShortCutList;
import labox.innovation.gameserver.network.clientpackets.RequestShortCutReg;
import labox.innovation.gameserver.network.clientpackets.RequestSkillInfo;
import labox.innovation.gameserver.network.clientpackets.RequestStarItem;
import labox.innovation.gameserver.network.clientpackets.RequestStopEffect;
import labox.innovation.gameserver.network.clientpackets.RequestUnEquipItem;
import labox.innovation.gameserver.network.clientpackets.RequestUserInfo;
import labox.innovation.gameserver.network.clientpackets.RequestWorldMapData;
import labox.innovation.gameserver.network.clientpackets.Say2;
import labox.innovation.gameserver.network.clientpackets.TestClientPacket;
import labox.innovation.gameserver.network.clientpackets.TradeDone;
import labox.innovation.gameserver.network.clientpackets.TradeLock;
import labox.innovation.gameserver.network.clientpackets.TradeRequest;
import labox.innovation.gameserver.network.clientpackets.UseItem;
import labox.innovation.gameserver.network.clientpackets.WareHouseRequest;
import labox.innovation.netcore.IAcceptFilter;
import labox.innovation.netcore.IClientFactory;
import labox.innovation.netcore.IMMOExecutor;
import labox.innovation.netcore.IPacketHandler;
import labox.innovation.netcore.MMOConnection;
import labox.innovation.netcore.ReceivablePacket;
import labox.innovation.util.Util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 状态数据包处理程序<BR>
 * 有状态的方法防止了服务器处理了不一致的包，例如:<BR>
 * <li>客户端发送了一个不含有角色的请求移动包. (处理这种包存在潜在的错误).</li> <li>客户端在已经认证过后发送了请求认证登陆的包. (潜在的溢出错误).</li> <BR>
 * <BR>
 * Note: If for a given exception a packet needs to be handled on more then one state, then it should be added to all these states.
 */
public final class L2GamePacketHandler implements IPacketHandler<L2GameClient>, IClientFactory<L2GameClient>, IMMOExecutor<L2GameClient>, IAcceptFilter {

	private static final Logger _log = LoggerFactory.getLogger(L2GamePacketHandler.class.getName());

	private boolean _accept = true;

	// implementation
	public ReceivablePacket<L2GameClient> handlePacket(ByteBuffer buf, L2GameClient client) {
		// 如果客户端已经与玩家分离开了，就不处理了
		if (client.isDetached())
			return null;

		int opcode = buf.get() & 0xFF;// 操作码
		System.out.println(buf.position());
		System.out.println("-----接受操作码  ：" + opcode);
		ReceivablePacket<L2GameClient> msg = null;
		GameClientState state = client.getState();

		switch (opcode) {
		case L2GameClientPacket.PTL_TESTPOROCAL:
			msg = new TestClientPacket();
			break;
		default:
			msg = new TestClientPacket();
			break;
		}
		//		
		// switch (state) {
		//		
		// case CONNECTED:
		// switch (opcode) {
		// case L2GameClientPacket.PTL_PROTOCOLVERSION:
		// msg = new ProtocolVersion();
		// break;
		// case L2GameClientPacket.PTL_AUTHLOGIN:
		// msg = new AuthLogin();
		// break;
		// case L2GameClientPacket.PTL_GAMEGUARDREPLY:
		// msg = new GameGuardReply();
		// break;
		// default:
		// printDebug(opcode, buf, state, client);
		// break;
		// }
		// break;
		// case AUTHED:
		// switch (opcode) {
		// case L2GameClientPacket.PTL_NEWCHARACTER:
		// msg = new NewCharacter();
		// break;
		// case L2GameClientPacket.PTL_CHARACTERCREAT:
		// msg = new CharacterCreate();
		// break;
		// case L2GameClientPacket.PTL_ENTERWORLD:
		// msg = new EnterWorld();
		// break;
		// case L2GameClientPacket.PTL_CHARACTERDELETE:
		// msg = new CharacterDelete();
		// break;
		// case L2GameClientPacket.PTL_CHARACTERRESTORE:
		// msg = new CharacterRestore(); // --
		// break;
		// case L2GameClientPacket.PTL_LOGOUT:
		// msg = new Logout();
		// break;
		// case L2GameClientPacket.PTL_GAMEGUARDREPLY:
		// msg = new GameGuardReply();
		// break;
		// default:
		// printDebug(opcode, buf, state, client);
		// break;
		//
		// }
		// break;
		// case IN_GAME:
		// switch (opcode) {
		// case L2GameClientPacket.PTL_LOGOUT:
		// msg = new Logout(); // -- 登出请求
		// break;
		// case L2GameClientPacket.PTL_GAMEGUARDREPLY:
		// msg = new GameGuardReply();
		// break;
		//
		// /*--------------------------------场景部分协议----------------------------------*/
		// case L2GameClientPacket.PTL_REQUESTSHORTCUTREG:
		// msg = new RequestShortCutReg();// 请求注册快捷
		// break;
		// case L2GameClientPacket.PTL_REQUESTSHORTCUTDEL:
		// msg = new RequestShortCutDel();// 请求删除快捷
		// break;
		// case L2GameClientPacket.PTL_REQUESTUSERINFO:
		// msg = new RequestUserInfo();// 请求角色的详细信息
		// break;
		// case L2GameClientPacket.PTL_REQUESTAUTOLEVELUP:
		// msg = new RequestAutoLevelUp();// 请求启用/禁用自动升级功能
		// break;
		// case L2GameClientPacket.PTL_REQUESTLEVELUP:
		// msg = new RequestLevelUp();// 客户端请求升级
		// break;
		// case L2GameClientPacket.PTL_REQUESTASSUGNPOINT:
		// msg = new RequestAssignPoint();// 客户端请求加点
		// break;
		// case L2GameClientPacket.PTL_REQUESTPARTYINFO:
		// msg = new RequestPartyInfo();// 查看队伍信息
		// break;
		// case L2GameClientPacket.PTL_SETPARTYINFO:
		// msg = new RequestSetPartyInfo();// 设置队伍信息
		// break;
		// case L2GameClientPacket.PTL_REQUESTCHANGEPARTYMODE:
		// msg = new RequestChangeDistribution();// 更改队伍分配方式
		// break;
		// case L2GameClientPacket.PTL_REQUESTNEARBYPLAYER:
		// msg = new RequestNearbyPlayer();// 查找附近玩家
		// break;
		// case L2GameClientPacket.PTL_REQUESTJOINPARTY:
		// msg = new RequestJoinParty();// 邀请加入队伍
		// break;
		// case L2GameClientPacket.PTL_REQUESTANSWERJOINPARTY:
		// msg = new RequestAnswerJoinParty();// 响应邀请入队请求
		// break;
		// case L2GameClientPacket.PTL_REQUESTOUTPARTYMEMBER:
		// msg = new RequestOutPartyMember();// 申请离队请求
		// break;
		// case L2GameClientPacket.PTL_REQUESTDISBANDPARTY:
		// msg = new RequestDisbandParty();// 解散队伍
		// break;
		// case L2GameClientPacket.PTL_REQUESTSHORTCUTLIST:
		// msg = new RequestShortCutList();
		// break;
		// case L2GameClientPacket.PTL_REQUESTSKILLINFO:
		// msg = new RequestSkillInfo();
		// break;
		// case L2GameClientPacket.PTL_REQUESTQUESTLIST:// --响应客户端请求任务列表
		// msg = new RequestQuestList();
		// break;
		// case L2GameClientPacket.PTL_REQUESTQUESTSELECT:
		// msg = new RequestQuestSelect();// 响应客户端请求任务查看
		// break;
		// case L2GameClientPacket.PTL_REQUESTQUESTABORT:
		// msg = new RequestQuestAbort();// 响应客户端请求放弃任务
		// break;
		// case L2GameClientPacket.PTL_RANK_LIST: // -- 响应客户端发送排行榜榜单信息消息
		// msg = new RankListRequest();
		// break;
		// case L2GameClientPacket.PTL_RANK: // -- 响应客户端发送排行榜信息消息
		// msg = new RankRequest();
		// break;
		// case L2GameClientPacket.PTL_REQUESTMERCHANT: // -- NPC商人逻辑
		// msg = new MerchantRequest();
		// break;
		// case L2GameClientPacket.PTL_REQUESTWORLDMAP:// 请求世界地图
		// msg = new RequestWorldMapData();
		// break;
		// case L2GameClientPacket.PTL_RADARINFO:// 雷达开启/关闭
		// msg = new RadarInfo();
		// break;
		//
		// /*--------------------------------战斗交互部分协议----------------------------------*/
		// case L2GameClientPacket.PTL_ATTACKREQUEST:
		// msg = new AttackRequest(); // -- 攻击请求
		// break;
		// case L2GameClientPacket.PTL_ATTACKCANCLE:
		// msg = new AttackCancle();// 请求攻击取消
		// break;
		// case L2GameClientPacket.PTL_ACTION:
		// msg = new Action();
		// break;
		// case L2GameClientPacket.PTL_REQUESTRESTARTPOINT:
		// msg = new RequestRestartPoint();
		// break;
		// case L2GameClientPacket.PTL_LOCATION:
		// msg = new Location(); // -- 同步坐标
		// break;
		// case L2GameClientPacket.PTL_REQUESTBYPASSTOSERVER:
		// msg = new RequestBypassToServer();// bypass命令逻辑处理
		// break;
		// case L2GameClientPacket.PTL_REQUESTMAGICSKILLUSE:
		// msg = new RequestMagicSkillUse();
		// break;
		// case L2GameClientPacket.PTL_REQUESTEFFECTBUFF:
		// msg = new RequestEffectBuff();
		// break;
		// case L2GameClientPacket.PTL_REQUESTSTOPEFFECT:
		// msg = new RequestStopEffect();
		// break;
		// case L2GameClientPacket.PTL_REQUESTCAHNGEPKMODEL:
		// msg = new RequestChangePkModel();// 请求改变PK模式
		// break;
		// case L2GameClientPacket.PTL_GETAUTOATTACKINFO:
		// msg = new AutoPKInfo();// 请求自动战斗配置信息
		// break;
		// case L2GameClientPacket.PTL_AUTOATTACKSET:
		// msg = new AutoPkSet();
		// break;
		// case L2GameClientPacket.PTL_AUTOATTACKSTATE:
		// msg = new AutoPkSetState();
		// break;
		//
		// /*------------------------------道具部分协议---------------------------*/
		// case L2GameClientPacket.PTL_REQUESTITEMLIST:
		// msg = new RequestItemList();
		// break;
		// case L2GameClientPacket.PTL_REQUESTEXRQITEMLINK:
		// msg = new RequestExRqItemLink();
		// break;
		// case L2GameClientPacket.PTL_USEITEM:
		// msg = new UseItem();
		// break;
		// case L2GameClientPacket.PTL_TRADEREQUEST:
		// msg = new TradeRequest(); // 请求交易
		// break;
		// case L2GameClientPacket.PTL_ANSWERTRADEREQUEST:
		// msg = new AnswerTradeRequest(); // 回应交易请求
		// break;
		// case L2GameClientPacket.PTL_CHANGETRADEITEM:
		// msg = new ChangeTradeItem(); // 改变交易列表中的物品
		// break;
		// case L2GameClientPacket.PTL_TRADELOCK:
		// msg = new TradeLock(); // 锁定交易
		// break;
		// case L2GameClientPacket.PTL_TRADEDONE:
		// msg = new TradeDone(); // 交易完成
		// break;
		// case L2GameClientPacket.PTL_REQUESTUNEQUIPITEM:
		// msg = new RequestUnEquipItem();
		// break;
		// case L2GameClientPacket.PTL_REQUESTDROPITEM:
		// msg = new RequestDropItem();
		// break;
		// case L2GameClientPacket.PTL_REQUESTPCSKILLLIST:
		// msg = new RequestPcSkillList();
		// break;
		// case L2GameClientPacket.PTL_REQUESTAQUIRESKILL:
		// msg = new RequestAquireskill();
		// break;
		// case L2GameClientPacket.PTL_WAREHOUSE_INVENTORY_MOVE: // --
		// // 响应客户端请求操作仓库信息消息
		// msg = new WareHouseRequest();
		// break;
		// case L2GameClientPacket.PTL_REQUESTIDENTIFYITEM:
		// msg = new RequestIdentifyItem();
		// break;
		// case L2GameClientPacket.PTL_REQUESTSTARITEM:
		// msg = new RequestStarItem();
		// break;
		// case L2GameClientPacket.PTL_REQUESTCOMPOSITEITEM:
		// msg = new RequestCompositeItem();
		// break;
		// case L2GameClientPacket.PTL_REQUESTFORGEITEM:
		// msg = new RequestForgeItem();
		// break;
		// case L2GameClientPacket.PTL_REQUESTFORGEITEMCHANGE:
		// msg = new RequestForgeItemChange();
		// break;
		// case L2GameClientPacket.PTL_SHOP_LIST: // -- 客户端请求商城列表
		// msg = new RequestShopItemsList();
		// break;
		// case L2GameClientPacket.PTL_SHOP: // -- 客户端请求购买商城中物品
		// msg = new RequestShopItem();
		// break;
		//
		// /*---------------------------------聊天系统-----------------------------------*/
		// case L2GameClientPacket.PTL_CHAT: // -- 聊天协议
		// msg = new Say2();
		// break;
		//
		// /*-----------------------------好友系统部分协议---------------------------------*/
		// case L2GameClientPacket.PTL_REQUESTFRIENDLIST:
		// msg = new RequestFriendList();// 请求好友列表
		// break;
		// case L2GameClientPacket.PTL_REQUESTADDFRIEND:
		// msg = new RequestFriendInvite();// 添加好友
		// break;
		// case L2GameClientPacket.PTL_REQUESTDELFRIEND:
		// msg = new RequestFriendDel();// 删除好友
		// break;
		// case L2GameClientPacket.PTL_REQUESTSEARCHFRIEND:
		// msg = new RequestSearchFriends();// 征友
		// break;
		// case L2GameClientPacket.PTL_REQUESTFRIENDNEWS:
		// msg = new RequestFriendsNews();// 好友动态
		// break;
		// case L2GameClientPacket.PTL_REQUESTSETINFO:
		// msg = new RequestSetInfo();// 设置征友基本信息
		// break;
		//
		// /*-------------------------------寄售系统-------------------------------------*/
		// case L2GameClientPacket.PTL_REQUESTCONSIGNMENTUI:
		// msg = new RequestConsignmentUI();// 打开寄售界面
		// break;
		// case L2GameClientPacket.PTL_REQUESTCANSHELVEITEMS:
		// msg = new RequestCanShelveItems();// 背包所有可寄售物品
		// break;
		// case L2GameClientPacket.PTL_REQUESTSHELVEITEMS:
		// msg = new RequestItemShelve();// 物品上架
		// break;
		// case L2GameClientPacket.PTL_REQUESTSHELFITEMS:
		// msg = new RequestItemShelf();// 物品下架
		// break;
		// case L2GameClientPacket.PTL_FETCHITEMOCNSIGNMENT:
		// msg = new FetchItemConsignment();// 取回下架物品
		// break;
		// case L2GameClientPacket.PTL_BUYITEMCONSIGNMENT:
		// msg = new BuyItemConsignment();// 购买寄售物品
		// break;
		// case L2GameClientPacket.PTL_REQUESTSHELVEOFSHELFITEM:
		// msg = new RequestShelveOfShelfItem();// 将下架物品上架
		// break;
		// case L2GameClientPacket.PTL_REQUESCONITEMBYCATEGORY:
		// msg = new RequestConItemByCategory();// 分类查找寄售物品
		// break;
		// case L2GameClientPacket.PTL_REQUESCONITEMHIGH:
		// msg = new RequestConItemHigh();// 高级查找寄售物品
		// break;
		// case L2GameClientPacket.PTL_REQUESTPAGETURING:
		// msg = new RequestPageTurning();// 请求已下架的物品
		// break;
		// case L2GameClientPacket.PTL_CHAT_SWITCH: // -- 聊天开关协议
		// msg = new ChatSwitchPacket();
		// break;
		// case L2GameClientPacket.PTL_RECHARGE: // 用户请求充值
		// msg = new RequestDeposit();
		// break;
		// case L2GameClientPacket.PTl_RECHARGE_List: // 请求充值列表
		// msg = new RequestDepositGUI();
		// break;
		// default:
		// this.printDebug(opcode, buf, state, client);
		// break;
		// }
		// break;
		// }
		return msg;
	}

	private void printDebug(int opcode, ByteBuffer buf, GameClientState state, L2GameClient client) {
		if (!Config.PACKET_HANDLER_DEBUG)
			return;

		int size = buf.remaining();
		_log.warn("Unknown Packet: " + Integer.toHexString(opcode) + " on State: " + state.name() + " Client: " + client.toString());
		byte[] array = new byte[size];
		buf.get(array);
		_log.warn(Util.printData(array, size));
	}

	@SuppressWarnings("unused")
	private void printDebugDoubleOpcode(int opcode, int id2, ByteBuffer buf, GameClientState state, L2GameClient client) {
		if (!Config.PACKET_HANDLER_DEBUG)
			return;
		int size = buf.remaining();
		_log.warn("Unknown Packet: " + Integer.toHexString(opcode) + ":" + Integer.toHexString(id2) + " on State: " + state.name() + " Client: " + client.toString());
		byte[] array = new byte[size];
		buf.get(array);
		_log.warn(Util.printData(array, size));
	}

	// impl
	public L2GameClient create(MMOConnection<L2GameClient> con) {
		return new L2GameClient(con);
	}

	public void execute(ReceivablePacket<L2GameClient> rp) {
		try {
			L2GameClient client = rp.getClient();
			if (client.getState() == GameClientState.IN_GAME) {
				client.addPacket(rp);
			} else {
				ThreadPoolManager.getInstance().execute(rp);
			}
		} catch (RejectedExecutionException e) {
			// if the server is shutdown we ignore
			if (!ThreadPoolManager.getInstance().isShutdown()) {
				_log.error("Failed executing: " + rp.getClass().getSimpleName() + " for Client: " + rp.getClient().toString(), Config.SERVER_ID, e);
			}
		}
	}

	/**
	 * 是否接受客户端的连接请求
	 */
	@Override
	public boolean accept(SocketChannel sc) {
		return _accept && LoginServerThread.getInstance().getAccountsInGameServerCount() < LoginServerThread.getInstance().getMaxPlayer();
	}

	public void setAccept(boolean accept) {
		_accept = accept;
	}
}
